﻿#include "AsmIndent.h"

CAsmIndent::CAsmIndent(void)
{
	m_LeftTabNum = 2;
	m_MidTabNum = 2;
	m_RightTabNum = 4;
	m_TabSpace = 4;
}

CAsmIndent::~CAsmIndent(void)
{
}

void CAsmIndent::AsmTidyMain( const char *pSourceIn, string &pSourceOut, unsigned int nUpperLower /*= 0*/, unsigned int nTabSpace /*= 4*/ )
{
	string strLine;
	size_t nInLen = strlen(pSourceIn);
	if (nInLen == 0)
	{
		return;
	}

	m_TabSpace = nTabSpace;
	size_t j = 0;
	for (size_t i = 0; i < nInLen; i++ )
	{
		if (pSourceIn[i] == '\n')
		{
			strLine.clear();
			strLine.append(pSourceIn + j, i - j + 1);
			LineParse(strLine, pSourceOut, nUpperLower);
			j = i + 1;
		}
	}
	if (j < nInLen)
	{
		strLine.clear();
		strLine.append(pSourceIn + j, nInLen - j);
		LineParse(strLine, pSourceOut, nUpperLower);
	}
}

void CAsmIndent::ToUpperOrLower( string &strLine, bool bUpper )
{
	if (bUpper)
	{
		for (string::size_type i = 0; i < strLine.size() && !(strLine[i] == ';' || strLine[i] == '\n'); i++)
		{
			strLine[i] = toupper(strLine[i]);
		}
	}
	else
	{
		for (string::size_type i = 0; i < strLine.size() && !(strLine[i] == ';' || strLine[i] == '\n'); i++)
		{
			strLine[i] = tolower(strLine[i]);
		}
	}
}

void CAsmIndent::LineParse( string &strLine, string &pSourceOut, unsigned int nUpperLower )
{
	trim(strLine);
	if (nUpperLower == 1 || nUpperLower == 2) //1.toupper 2.tolower
	{
		ToUpperOrLower(strLine, nUpperLower == 1?true:false);
	}
	const char *pLineEnd = "\r\n";

	// 1)假如开头是注释符号或者空行，不解析
	if (strLine.empty() || strLine[0] == ';')
	{
		pSourceOut.append(strLine);
		pSourceOut.append(pLineEnd);
		return;
	}

	// 2)查找":"位置
	string::size_type nColonPos = strLine.find(':');
	if (strLine.find_first_of(" \t", 0) < nColonPos)
	{
		nColonPos = string::npos;
	}

	// 3)查找";"位置
	string::size_type nSemicolonPos = strLine.find(';');
	if (nSemicolonPos < nColonPos)
	{
		nColonPos = string::npos;
	}

	// 4)提取中间内容
	string strMidText = strLine.substr(nColonPos + 1, nSemicolonPos == string::npos?string::npos:nSemicolonPos - nColonPos - 1);
	trim(strMidText);

	// 5)中间内容为空，则不解析
	if (strMidText.empty())
	{
		int nTabNum = m_LeftTabNum + m_MidTabNum + m_RightTabNum;
		if (nColonPos != string::npos)
		{
			pSourceOut.append(strLine.substr(0, nColonPos + 1));
			nTabNum -= (nColonPos + 1) / m_TabSpace;
			if (nTabNum <= 0)
			{
				nTabNum = 1;
			}
		}
		if (nSemicolonPos != string::npos)
		{
			pSourceOut.append(nTabNum, '\t');
			pSourceOut.append(strLine.substr(nSemicolonPos));
		}
		pSourceOut.append(pLineEnd);
		return;
	}
	if (nColonPos != string::npos)
	{
		pSourceOut.append(strLine.substr(0, nColonPos + 1));
		pSourceOut.append(pLineEnd);
	}

	// 6)解析指令行
	// 6.1)查找空格位置
	string::size_type nSpacePos = strMidText.find_first_of(" \t");
	if (nSpacePos == string::npos)
	{
		pSourceOut.append(m_LeftTabNum, '\t');
		pSourceOut.append(strMidText);
		int nTabNum = m_MidTabNum + m_RightTabNum;
		nTabNum -= strMidText.size() / m_TabSpace;
		if (nTabNum <= 0)
		{
			nTabNum = 1;
		}
		if (nSemicolonPos != string::npos)
		{
			pSourceOut.append(nTabNum, '\t');
			pSourceOut.append(strLine.substr(nSemicolonPos));
		}
		pSourceOut.append(pLineEnd);
		return;
	}

	// 6.2)解析空格之后的内容，删除多余的空格、制表符
	string::size_type nSecondPos = strMidText.find_first_not_of(" \t", nSpacePos);
	for (string::size_type i = strMidText.size() - 1; i > nSecondPos; i--)
	{
		if (strMidText[i] == ' ' || strMidText[i] == '\t')
		{
			strMidText[i] = ' ';
			if (strMidText[i - 1] == ' ' || strMidText[i - 1] == '\t')
			{
				strMidText.erase(i, 1);
			}
		}
		else if (strMidText[i] == ',')
		{
			if (strMidText[i - 1] == ' ' || strMidText[i - 1] == '\t')
			{
				strMidText[i - 1] = ',';
				strMidText.erase(i, 1);
			}
		}
	}

	// 6.3)从后开始，遇到","则空一格后移
	string::size_type nRCommaPos = strMidText.rfind(',', strMidText.size() - 1);
	while (nRCommaPos != string::npos && nRCommaPos >= nSecondPos)
	{
		strMidText.replace(nRCommaPos, strMidText.find_first_not_of(" \t", nRCommaPos + 1) - nRCommaPos, ", ");
		nRCommaPos = strMidText.rfind(',', nRCommaPos - 1);
	}

	// 6.4)替换成制表符
	int nTabNum = m_MidTabNum;
	nTabNum -= nSpacePos / m_TabSpace;
	if (nTabNum <= 0)
	{
		nTabNum = 1;
	}
	int nOperandLen = strMidText.size() - nSecondPos;
	strMidText.replace(nSpacePos, nSecondPos - nSpacePos, nTabNum, '\t');

	pSourceOut.append(m_LeftTabNum, '\t');
	pSourceOut.append(strMidText);
	nTabNum = m_RightTabNum - nOperandLen / m_TabSpace;
	if (nTabNum <= 0)
	{
		nTabNum = 1;
	}
	if (nSemicolonPos != string::npos)
	{
		pSourceOut.append(nTabNum, '\t');
		pSourceOut.append(strLine.substr(nSemicolonPos));
	}
	pSourceOut.append(pLineEnd);

	return;
}
